﻿using System;
using Zo.Domain.UnitOfWorks;
using Zo.Events;
using Zo.IoC;

namespace Zo.Domain
{
    public abstract class Entity
    {
        private int? _requestedHashCode;

        /// <summary>
        /// 实体唯一标识。
        /// </summary>
        public virtual int Id { get; private set; }

        /// <summary>
        /// 改变当前实体编号。
        /// </summary>
        /// <param name="identity">实体编号。</param>
        public void ChangeCurrentIdentity(int identity)
        {
            Id = identity;
        }

        /// <summary>
        /// 增加领域事件。
        /// </summary>
        /// <param name="eventItem">领域事件。</param>
        public void AddEvent(IEvent eventItem)
        {
            IoCManager.Instance.GetService<IUnitOfWorkFactory>().Get().AddEvent(eventItem);
        }

        #region 重载操作符

        public bool IsTransient()
        {
            return this.Id == default(Int32);
        }

        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Entity))
                return false;

            if (Object.ReferenceEquals(this, obj))
                return true;

            if (this.GetType() != obj.GetType())
                return false;

            Entity item = (Entity)obj;

            if (item.IsTransient() || this.IsTransient())
                return false;
            else
                return item.Id == this.Id;
        }

        public override int GetHashCode()
        {
            if (!IsTransient())
            {
                if (!_requestedHashCode.HasValue)
                    _requestedHashCode = this.Id.GetHashCode() ^ 31; // XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)

                return _requestedHashCode.Value;
            }
            else
                return base.GetHashCode();
        }

        public static bool operator ==(Entity left, Entity right)
        {
            if (Object.Equals(left, null))
                return (Object.Equals(right, null)) ? true : false;
            else
                return left.Equals(right);
        }

        public static bool operator !=(Entity left, Entity right)
        {
            return !(left == right);
        }

        #endregion 重载操作符
    }
}